Baigiamojo darbo tema¶

Transportas. Lietuvos transporto priemonių parkas

Baigiamojo darbo pavadinimas¶

Lietuvos transporto priemonių parko analizė

Baigiamojo darbo aprašymas¶

Hipotezės:

  1. Didžiąją dalį Lietuvos transporto priemonių parko sudaro lengvieji automobiliai.
  2. Juridinių asmenų valdomos transporto priemonės naujesnės nei fizinių.
  3. Naujausius automobilius vairuoja 29-53 m. amžiaus asmenys.
  4. Didžiuosiuose miestuose žmonės vairuoja naujesnius automobilius nei rajonuose taip pat dažniau renkasi premium markės automobilius.
  5. Elektra varomų traunsporto priemonių lietuvoje daugėja.

Tikslai:

  1. Išanalizuoti Lietuvos transporto priemonių parko duomenis pagal transporto priemonių tipus, markes pagaminimo datas.
  2. Naudojant turimą informacija atlikti valdytojų amžiaus bei gyvenamosios vietos analizę pagal tai kokio tipo/amžiaus/klasės transporto priemonę jie vairuoja.
  3. Palyginti 2022 ir 2023 metų duomenis siekiant suprasti kaip keičiasi transporto priemonių parkas Lietuvoje.

Uždaviniai:

  1. Darbui reikalingų duomenų suradimas ir sukėlimas į Google colab.
  2. Failų analizė, duomenų valymas, papildomų stulpelių kūrimas, funkcijų taikymas, nereikalingos informacijos/stulpelių naikinimas.
  3. Papidlomų lentelių kūrimas, funkcijų taikymas, tvarkant duomenis, lentelių sujungimas.
  4. Hipotezių tikrinimas pasitelkiant statistinę ir grafinę duomenų analizę python kalba.

Išvados:

  1. Duomenys rasti atvirų duomenų duomenų bazėje VĮ Regitra tinklapyje.
  2. Duomenų kokybė nebuvo labai gera, daug reikšmių buvo tuščių, suvedant duomenis nebuvo naudoti klasifikatoriai tad dalyje stulpelių tai pačiai reikšmei nustatyti buvo naudojami skirtingi tekstai.
  3. Duomenys sutvarkyti, išfiltruoti, pakeisti duomenų formatai, pasitelktos papildomos lentelės papildomų stulpelių kūrimui, panaudotos funkcijos, taip pat sukurtos kelios naujos funkcijos duomenų pildymui.
  4. Pirmoji Hipotezė patvirtinta - didžiausią dalį transporto priemonių Lietuvoje sudaro Lengvieji automobiliai.
  5. Antroji Hipotezė patvirtinta. Juridiniai asmenys valdo žymiai naujesnes transporto priemones, jų amžiaus vidurkis 11 metų, tuo tarpu fizinių asmenų transporto priemonių amžiaus vidurkis beveik 17 m.
  6. Trečioji hipotezė patvirtinta matome kad vidutiniškai naujausius automobilius vairuoja asmenys intervale nuo 29 iki 53 m.
  7. Ketvirtoji Hipotezė patvirtinta iš dalies, iš tiesų, vidutiniškai naujausius automobilius vairuoja didmiesčių gyventojai, naujausi automobiliai yra ekonominės klasės ir važinėja Vilniuje. Premium klasės automobilių didmiesčiuose yra daugiausia, tačiau tik todėl kad čia yra daugiausia gyventojų,tikslesnius duomenis gauname jei skaičiuojame procentinę dalį Premium klasės automobilių ir čia didieji miestai yra lentelės apatinėje dalyje.
  8. Penktosios hipotezės negalime nei patvirtinti nei paneigti, kadangi 2023 m. neturime duomenų net apie 535.670 automobilių degalų tipą, kai 2022 tokių įrašų tik 292.097 esant daugiau nei 15% skirtumui teisingų išvadų padaryti negalėsime.
  9. Mašininio mokymosi algoritmų pritaikyti nepavyko, kadangi nebuvo surasta duomenų ryšių, kuriais remiantis būtų galima tinkamai apmokyti modelį.
In [249]:
import matplotlib
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np

Pirminis duomenų paruošimas 2022 ir 2023 m. failams:

In [250]:
# # 2023 m:
# from google.colab import drive
# drive.mount('/drive')
# transport2023 = pd.read_csv("/drive/My Drive/Project/Atviri_TP_parko_duomenys 2023.csv")
# transport2023 = transport2023.drop(['GAMINTOJO_PAV', 'GAMINTOJO_PAV_BAZ',
#        'TIPAS', 'VARIANTAS', 'VERSIJA', 'ES_TIPO_PATVIRTINIMO_NR',
#       'NAC_TIPO_PATVIRTINIMO_NR', 'INDIVIDUAL_PATVIRTINIMO_NR',
#        'INTERPOLIACIJA', 'UZBAIGTUMO_PAKOPA',
#        'KATEGORIJA_PILNAI', 'KEB_KODAS',
#        'SPEC_KODAS', 'SPEC_PAVADINIMAS', 'KEB_KODAS_ES', 'NUOSAVA_MASE',
#       'MAKS_MASE_F2', 'MAKS_MASE_F5',
#        'BANDOMOJI_MASE', 'SUKIU_SK',
#        'DEGALU_REZIMAS', 'PAVARU_DEZES_TIPAS',
#        'EKO_NAUJOVES_KODAS', 'CO2_SUMAZEJIMAS_NEDC', 'CO2_SUMAZEJIMAS_WLTP',
#        'ELEKTR_ENERG_SANAUD_NEDC', 'ELEKTR_ENERG_SANAUD_WLTP_E',
#        'ELEKTR_ENERG_SANAUD_WLTP_H', 'ELEKTRINE_RIDA_NEDC',
#        'ELEKTRINE_RIDA_WLTP_E', 'ELEKTRINE_RIDA_WLTP_H',
#        'TERSALU_NORM_AKTO_NR', 'RATU_BAZE', 'TV_PLOTIS1', 'TV_PLOTIS2',
#       'GALIOS_MASES_SANT', 'GALIOJIMO_LAIK','DAE_STATUSAS'], axis=1)
# transport2023['ID'] = range(5000000, 5000000 + len(transport2023))
# transport2023 = transport2023.drop(transport2023[transport2023['MARKE'] == "Nuasmeninta"].index)
# transport2023['Duomenų metai'] = 2023
# transport2023[['VALDYTOJO METAI 1', 'VALDYTOJO METAI2']] = transport2023['VALD_GIM_DAT_INT'].str.split('-', expand=True)
# transport2023['VALDYTOJO METAI 1']= pd.to_numeric(transport2023['VALDYTOJO METAI 1'], errors='coerce', downcast='integer')
# transport2023['VALDYTOJO METAI2']= pd.to_numeric(transport2023['VALDYTOJO METAI2'], errors='coerce', downcast='integer')
# transport2023['AMZIUS1'] = np.where(transport2023['VALDYTOJO METAI 1'].notna(), transport2023['Duomenų metai'] - transport2023['VALDYTOJO METAI 1'], np.nan)
# transport2023['AMZIUS2'] = np.where(transport2023['VALDYTOJO METAI2'].notna(), transport2023['Duomenų metai'] - transport2023['VALDYTOJO METAI2'], np.nan)
# transport2023['AMZIAUS INT'] = transport2023['AMZIUS2'].astype(str).str.replace('\..*', '', regex=True) + '-' + transport2023['AMZIUS1'].astype(str).str.replace('\..*', '', regex=True)
# transport2023['AMZIAUS INT'] = transport2023['AMZIAUS INT'].replace('nan-nan', np.nan, regex=True)
# from google.colab import drive
# drive.mount('/drive')
# makes = pd.read_excel("/drive/My Drive/Project/Makes2.xlsx")
# from google.colab import drive
# drive.mount('/drive')
# models = pd.read_excel("/drive/My Drive/Project/Models2.xlsx",)

# # sukuriame žodyną markėms:
# mapping_dict = makes.set_index('Marke Regitra')['Marke'].to_dict()


# # Sukuriame funkciją kuri pildys markes žodyno reikšmėmis
# def map_marker(row):
#     if row['MARKE'] in mapping_dict:
#         return mapping_dict[row['MARKE']]
#     return row['MARKE']

# # Pakeičiame reikšmes:
# transport2023['MARKE'] = transport2023.apply(map_marker, axis=1)

# # sukuriame žodyną modeliams:
# mapping_dict_model = models.set_index('Modelis regitra')['Modelis'].to_dict()


# # Sukuriame funkciją kuri pildys modelius žodyno reikšmėmis
# def map_models(row):
#     if row['KOMERCINIS_PAV'] in mapping_dict_model:
#         return mapping_dict_model[row['KOMERCINIS_PAV']]
#     return row['KOMERCINIS_PAV']

# # Pakeičiame reikšmes:
# transport2023['KOMERCINIS_PAV'] = transport2023.apply(map_models, axis=1)
# transport2023
# transport2023.to_csv('TP2023.csv', index=False)
# from google.colab import files
# files.download('TP2023.csv')

# # 2022 m.:
# from google.colab import drive
# drive.mount('/drive')
# transport2022 = pd.read_csv("/drive/My Drive/Project/Atviri_TP_parko_duomenys2022.csv")
# pd.set_option('display.max_columns', None)
# transport2022.shape
# transport2022 = transport2022.drop(['GAMINTOJO_PAV', 'GAMINTOJO_PAV_BAZ',
#        'TIPAS', 'VARIANTAS', 'VERSIJA', 'ES_TIPO_PATVIRTINIMO_NR',
#       'NAC_TIPO_PATVIRTINIMO_NR', 'INDIVIDUAL_PATVIRTINIMO_NR',
#        'INTERPOLIACIJA', 'UZBAIGTUMO_PAKOPA',
#        'KATEGORIJA_PILNAI', 'KEB_KODAS',
#        'SPEC_KODAS', 'SPEC_PAVADINIMAS', 'KEB_KODAS_ES', 'NUOSAVA_MASE',
#       'MAKS_MASE_F2', 'MAKS_MASE_F5',
#        'BANDOMOJI_MASE', 'SUKIU_SK',
#        'DEGALU_REZIMAS', 'PAVARU_DEZES_TIPAS',
#        'EKO_NAUJOVES_KODAS', 'CO2_SUMAZEJIMAS_NEDC', 'CO2_SUMAZEJIMAS_WLTP',
#        'ELEKTR_ENERG_SANAUD_NEDC', 'ELEKTR_ENERG_SANAUD_WLTP_E',
#        'ELEKTR_ENERG_SANAUD_WLTP_H', 'ELEKTRINE_RIDA_NEDC',
#        'ELEKTRINE_RIDA_WLTP_E', 'ELEKTRINE_RIDA_WLTP_H',
#        'TERSALU_NORM_AKTO_NR', 'RATU_BAZE', 'TV_PLOTIS1', 'TV_PLOTIS2',
#       'GALIOS_MASES_SANT', 'GALIOJIMO_LAIK','DAE_STATUSAS'], axis=1)
# transport2022.columns
# transport2022['ID'] = range(1, len(transport2022) + 1)
# transport2022['MARKE'].value_counts()
# transport2022.dtypes
# transport2022 = transport2022.drop(transport2022[transport2022['MARKE'] == "Nuasmeninta"].index)
# transport2022['Duomenų metai'] = 2022
# transport2022[['VALDYTOJO METAI 1', 'VALDYTOJO METAI2']] = transport2022['VALD_GIM_DAT_INT'].str.split('-', expand=True)
# transport2022['VALDYTOJO METAI 1']= pd.to_numeric(transport2022['VALDYTOJO METAI 1'], errors='coerce', downcast='integer')
# transport2022['VALDYTOJO METAI2']= pd.to_numeric(transport2022['VALDYTOJO METAI2'], errors='coerce', downcast='integer')
# transport2022['AMZIUS1'] = np.where(transport2022['VALDYTOJO METAI 1'].notna(), transport2022['Duomenų metai'] - transport2022['VALDYTOJO METAI 1'], np.nan)
# transport2022['AMZIUS2'] = np.where(transport2022['VALDYTOJO METAI2'].notna(), transport2022['Duomenų metai'] - transport2022['VALDYTOJO METAI2'], np.nan)
# transport2022['AMZIAUS INT'] = transport2022['AMZIUS2'].astype(str).str.replace('\..*', '', regex=True) + '-' + transport2022['AMZIUS1'].astype(str).str.replace('\..*', '', regex=True)
# transport2022['AMZIAUS INT'] = transport2022['AMZIAUS INT'].replace('nan-nan', np.nan, regex=True)
# from google.colab import drive
# drive.mount('/drive')
# makes = pd.read_excel("/drive/My Drive/Project/Makes2.xlsx")
# from google.colab import drive
# drive.mount('/drive')
# models = pd.read_excel("/drive/My Drive/Project/Models2.xlsx",)
# mapping_dict = makes.set_index('Marke Regitra')['Marke'].to_dict()


# # Sukuriame funkciją kuri pildys markes žodyno reikšmėmis
# def map_marker(row):
#     if row['MARKE'] in mapping_dict:
#         return mapping_dict[row['MARKE']]
#     return row['MARKE']

# # Pakeičiame reikšmes:
# transport2022['MARKE'] = transport2022.apply(map_marker, axis=1)
# mapping_dict_model = models.set_index('Modelis regitra')['Modelis'].to_dict()


# # Sukuriame funkciją kuri pildys markes žodyno reikšmėmis
# def map_models(row):
#     if row['KOMERCINIS_PAV'] in mapping_dict_model:
#         return mapping_dict_model[row['KOMERCINIS_PAV']]
#     return row['KOMERCINIS_PAV']

# # Pakeičiame reikšmes:
# transport2022['KOMERCINIS_PAV'] = transport2022.apply(map_models, axis=1)
# # saugome duomenis
# transport2022.to_csv('TP2022.csv', index=False)
# from google.colab import files
# files.download('TP2023.csv')

Antrinis duomenų apdorojimas

In [251]:
from google.colab import drive
drive.mount('/drive')
tp2022 = pd.read_csv("/drive/My Drive/Project/TP2022.csv")
tp2023 = pd.read_csv("/drive/My Drive/Project/TP2023.csv")
Drive already mounted at /drive; to attempt to forcibly remount, call drive.mount("/drive", force_remount=True).
<ipython-input-251-abd811160dff>:3: DtypeWarning: Columns (2,6,12,15,18) have mixed types. Specify dtype option on import or set low_memory=False.
  tp2022 = pd.read_csv("/drive/My Drive/Project/TP2022.csv")
<ipython-input-251-abd811160dff>:4: DtypeWarning: Columns (2,6,15,18) have mixed types. Specify dtype option on import or set low_memory=False.
  tp2023 = pd.read_csv("/drive/My Drive/Project/TP2023.csv")
In [252]:
pd.set_option('display.max_columns', None)
In [253]:
tp2022.shape
Out[253]:
(2006009, 38)
In [254]:
tp2023.shape
Out[254]:
(2101585, 38)

Trumpa failo analizė (pirminiame etape analizuojami 2023 m. duomenys)

In [255]:
tp2023.describe()
Out[255]:
NUOSAVA_MASE_BAZ DARBINIS_TURIS GALIA GALIA_ELEKTR CO2_KIEKIS CO2_KIEKIS_WLTP MAKS_GREITIS STOVIMU_VIETU_SK GAMYBOS_METAI MODELIO_METAI RIDA ID Duomenų metai VALDYTOJO METAI 1 VALDYTOJO METAI2 AMZIUS1 AMZIUS2
count 1202.000000 1.842816e+06 1.846732e+06 31297.000000 982616.000000 118027.000000 809033.000000 3106.000000 124869.000000 89614.000000 3.183490e+05 2.101585e+06 2101585.0 1.639306e+06 1.639306e+06 1.639306e+06 1.639306e+06
mean 2109.396839 2.477838e+03 1.149121e+02 51.034075 159.881271 156.363857 175.230978 100.178042 1995.280366 2009.515355 2.115250e+05 6.050792e+06 2023.0 1.971281e+03 1.975281e+03 5.171914e+01 4.771914e+01
std 566.534599 5.386015e+03 6.271860e+03 62.408823 44.356977 44.699206 47.535584 1190.287959 8.764452 22.311781 4.312503e+05 6.066755e+05 0.0 1.477741e+01 1.477741e+01 1.477741e+01 1.477741e+01
min 0.000000 4.000000e+00 1.000000e-01 1.200000 1.000000 0.000000 19.000000 0.000000 1297.000000 0.000000 0.000000e+00 5.000000e+06 2023.0 1.915000e+03 1.919000e+03 3.000000e+00 -1.000000e+00
25% 1954.000000 1.686000e+03 7.600000e+01 10.000000 132.000000 131.000000 157.000000 12.000000 1990.000000 2007.000000 1.511740e+05 5.525396e+06 2023.0 1.960000e+03 1.964000e+03 3.800000e+01 3.400000e+01
50% 2102.000000 1.968000e+03 9.600000e+01 53.000000 156.000000 147.000000 186.000000 47.500000 1994.000000 2013.000000 2.073160e+05 6.050792e+06 2023.0 1.970000e+03 1.974000e+03 5.300000e+01 4.900000e+01
75% 2205.000000 2.309000e+03 1.200000e+02 85.300000 181.000000 174.000000 205.000000 65.000000 2002.000000 2016.000000 2.545290e+05 6.576188e+06 2023.0 1.985000e+03 1.989000e+03 6.300000e+01 5.900000e+01
max 9965.000000 2.664176e+06 8.520010e+06 6100.000000 2836.000000 425.000000 9915.000000 27000.000000 2023.000000 6074.000000 9.815383e+07 7.101584e+06 2023.0 2.020000e+03 2.024000e+03 1.080000e+02 1.040000e+02
In [255]:
 

Kadangi bus daromi duomenų keitimai ir vėliau analizei naudosime ir 2022 metu duomenis lenteles sujungiame į df

In [256]:
df = pd.concat([tp2022, tp2023], axis=0, ignore_index=True)

Lauką KATEGORIJA KLASE_ pakeičiame į tekstinius kategorijos pavadinimus.

In [257]:
df["KATEGORIJA_KLASE"].unique()
Out[257]:
array(['M1', 'N1', 'N2', 'O1', 'N3', 'O2', 'L3', 'O4', 'L1', 'O3', 'L7',
       'L6', 'M3', 'L4', 'L5', 'M2', 'L2', 'GK'], dtype=object)
In [257]:
 
In [258]:
df["KATEGORIJA_KLASE"] = df['KATEGORIJA_KLASE'].replace({
    'M1':'Lengvieji automobiliai',
    'N1':'Krovininiai automobiliai iki 3,5t',
    "N2":'Krovininiai automobiliai iki 12t',
    "N3":'Krovininiai automobiliai virš 12t',
    'O2':'Krovininiu automobiliu priekabos',
    'L3':'Motociklai, mopedai',
    'O4':'Krovininiu automobiliu priekabos',
    'L1':'Lengvųjų automobilių priekabos',
    'O3':'Krovininiu automobiliu priekabos',
    'L7':'Motociklai, mopedai',
    'L6':'Motociklai, mopedai',
    'M3':'Autobusai',
    'L4':'Motociklai, mopedai',
    'L5':'Motociklai, mopedai',
    'M2':'Autobusai',
    'L2':'Motociklai, mopedai',
    'GK':'Motociklai, mopedai',
    'O1':'Lengvųjų automobilių priekabos',
})

Iš stulpelio savivaldybe sukuriame papildomą stulpelį kuriame turėsime informaciją ar miestas Didmiestis ar ne. Didmiesčiais laikysime tik 5 didžiausius LT miesus

In [259]:
df["AR DIDMIESTIS"] = df['SAVIVALDYBE'].apply(lambda x: 1 if x in ['VILNIAUS M. SAV.', 'KAUNO M. SAV.', 'KLAIPĖDOS M. SAV.', 'PANEVĖŽIO M. SAV.', 'ŠIAULIŲ M. SAV.' ] else 0)
In [259]:
 

Suskaičiuojamas TP amžius pagal pirmos registracijos datą

In [260]:
df['PAGAMINIMO METAI'] =df.apply(lambda row: row['PIRM_REG_DATA'].split('-')[0] if pd.notna(row['PIRM_REG_DATA']) else pd.NA, axis=1)
In [261]:
df['PAGAMINIMO METAI'] = df['PAGAMINIMO METAI'].fillna(1722)
df['TP AMZIUS'] = df["Duomenų metai"] - df['PAGAMINIMO METAI'].astype(int)
df.head()
Out[261]:
MARKE KOMERCINIS_PAV VAIRAS_DESINEJE KATEGORIJA_KLASE KEB_PAVADINIMAS NUOSAVA_MASE_BAZ MAKS_MASE DARBINIS_TURIS GALIA GALIA_ELEKTR DEGALAI ELEKTRINE_TP HIBRIDINES_TP_KATEGORIJA CO2_KIEKIS CO2_KIEKIS_WLTP TERSALU_LYGIS SPALVA MAKS_GREITIS SEDIMU_VIETU_SK STOVIMU_VIETU_SK GAMYBOS_METAI MODELIO_METAI RIDA PIRM_REG_DATA PIRM_REG_DATA_LT PASKUTINES_REG_DATA KILMES_SALIS VALD_TIPAS VALD_GIM_DAT_INT SAVIVALDYBE APSKRITIS ID Duomenų metai VALDYTOJO METAI 1 VALDYTOJO METAI2 AMZIUS1 AMZIUS2 AMZIAUS INT AR DIDMIESTIS PAGAMINIMO METAI TP AMZIUS
0 VOLVO VOLVO B + V70 NaN Lengvieji automobiliai Universalas NaN 2180.0 1999.0 107.0 NaN -- N NaN 206.0 NaN NaN PILKA 200.0 5.0 NaN NaN NaN 223622.0 2008-06-25 2022-09-28 2022-09-28 SWE Fizinis 1970-1974 ŠIRVINTŲ R. SAV. VIL 1 2022 1970.0 1974.0 52.0 48.0 48-52 0 2008 14
1 IVECO DAILY NaN Krovininiai automobiliai iki 3,5t Kombinuotas furgonas NaN 3500.0 2998.0 129.0 NaN -- N NaN NaN 293.0 EURO6 E BALTA 160.0 7.0 NaN NaN NaN NaN 2022-09-28 2022-09-28 2022-09-28 NaN Juridinis NaN ŠIAULIŲ M. SAV. ŠIA 2 2022 NaN NaN NaN NaN NaN 1 2022 0
2 MERCEDES BENZ 316 CDI-9036-3.55T-KASTEN/355 NaN Krovininiai automobiliai iki 12t NaN NaN 3550.0 2680.0 115.0 NaN -- N NaN NaN NaN NaN BALTA NaN 3.0 NaN NaN NaN NaN 2006-03-20 2022-09-28 2022-09-28 FIN Fizinis 1995-1999 ŠIAULIŲ M. SAV. ŠIA 3 2022 1995.0 1999.0 27.0 23.0 23-27 1 2006 16
3 VW SHARAN NaN Lengvieji automobiliai NaN NaN 2470.0 1896.0 85.0 NaN -- N NaN 174.0 NaN NaN MĖLYNA 181.0 7.0 NaN NaN NaN NaN 2002-11-25 2022-09-28 2022-09-28 DEU Juridinis NaN ŠAKIŲ R. SAV. MAR 4 2022 NaN NaN NaN NaN NaN 0 2002 20
4 RESPO 750V411T160 NaN Lengvųjų automobilių priekabos Centrinės ašies NaN 750.0 NaN NaN NaN -- N NaN NaN NaN NaN PILKA 140.0 NaN NaN NaN NaN NaN 2022-03-07 2022-03-07 2022-03-07 NaN Fizinis 1965-1969 VILNIAUS M. SAV. VIL 5 2022 1965.0 1969.0 57.0 53.0 53-57 1 2022 0
In [262]:
df["TP AMZIUS"].unique()
Out[262]:
array([ 14,   0,  16,  20,   6,  12,   4,   5,  17,  11,   9,  15,  13,
         3,  10,   7,  39,   8,  28, 300,  21,  18,  22,   1,  19,  25,
        30,  44,   2,  26,  27,  23,  24,  35,  38,  29,  31,  33,  37,
        32,  34,  36,  46,  45,  43,  42,  41,  40,  47,  48,  51,  49,
        52,  57,  56,  58,  55,  62,  50,  53,  60,  70,  59,  68,  71,
        54,  83,  67,  66,  65,  91,  81,  76,  69,  61, 301,  63,  88,
        72,  82,  64,  92,  77,  73,  84])
In [263]:
df['TP AMZIUS'] = df['TP AMZIUS'].replace([300, 301], "NaN")
In [264]:
df["TP AMZIUS"].unique()
Out[264]:
array([14, 0, 16, 20, 6, 12, 4, 5, 17, 11, 9, 15, 13, 3, 10, 7, 39, 8, 28,
       'NaN', 21, 18, 22, 1, 19, 25, 30, 44, 2, 26, 27, 23, 24, 35, 38,
       29, 31, 33, 37, 32, 34, 36, 46, 45, 43, 42, 41, 40, 47, 48, 51, 49,
       52, 57, 56, 58, 55, 62, 50, 53, 60, 70, 59, 68, 71, 54, 83, 67, 66,
       65, 91, 81, 76, 69, 61, 63, 88, 72, 82, 64, 92, 77, 73, 84],
      dtype=object)

Lengvuosius automobilius suskirstome į segmentus "Premium" "Vidutinis" "Ekonominis"

In [265]:
markes = df[df['KATEGORIJA_KLASE'] == 'Lengvieji automobiliai']['MARKE'].value_counts()
markes = markes.to_frame().reset_index()
In [266]:
markes.to_excel('markes.xlsx', index=False)
from google.colab import files
files.download('markes.xlsx')
In [267]:
from google.colab import drive
drive.mount('/drive')
klases = pd.read_excel("/drive/My Drive/Project/Klases.xlsx")
Drive already mounted at /drive; to attempt to forcibly remount, call drive.mount("/drive", force_remount=True).
In [268]:
klases
Out[268]:
index klase
0 VW Vidutinė
1 AUDI Premium
2 TOYOTA Vidutinė
3 OPEL Vidutinė
4 BMW Premium
... ... ...
61 SCION Vidutinė
62 HUMMER Premium
63 VOLKSWAGEN-VW VOLKSWAGEN. VW Vidutinė
64 Jaguar Land Rover Limited Premium
65 ZAZ Ekonominė

66 rows × 2 columns

In [269]:
df['KLASE'] = "Nezinoma"
In [270]:
mapping_dict_klases = klases.set_index('index')['klase'].to_dict()
# Sukuriame funkciją kuri pildys klases žodyno reikšmėmis
def map_klases(row):
    if row['MARKE'] in mapping_dict_klases:
        return mapping_dict_klases[row['MARKE']]
    return "Nezinoma"
# Pakeičiame reikšmes:
df['KLASE'] = df.apply(map_klases, axis=1)

Duomenų analizė¶

Pirmoms keturioms hipotezėms tikrinti naudosime 2023 m. duomenis

Tikriname pirmą hipotezę "Didžiąją dalį Lietuvos transporto priemonių parko sudaro lengvieji automobiliai"

In [271]:
df_2023 = df[(df["Duomenų metai"] == 2023)]
In [272]:
# sukuriame kryžminė lentele
cross_tab = pd.crosstab(df_2023['KATEGORIJA_KLASE'], columns='count')

fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(15, 8))

# stulpelinis grafikas
sns.countplot(x='KATEGORIJA_KLASE', data=df_2023, ax=axes[0])
axes[0].set_title("Transporto priemonės pagal tipą")
axes[0].set_xticklabels(axes[0].get_xticklabels(), rotation=90)
# heatmap lentele
sns.heatmap(cross_tab, annot=True, cmap='viridis', fmt='d', cbar=False, ax=axes[1])
axes[1].set_title("Transporto priemonės pagal tipą")
axes[1].set_xlabel("KATEGORIJA_KLASE")
axes[1].set_ylabel("Count")
plt.tight_layout()
plt.show()

Pirmoji Hipotezė patvirtinta - didžiausią dalį transporto priemonių Lietuvoje sudaro Lengvieji automobiliai


Tikriname antrą hipotezę "Juridinių asmenų valdomos transporto priemonės naujesnės nei fizinių"

In [273]:
# analizuojame tik lengvuosius automobilius ir tik tuos kurie turi amžiaus reikšmę kad galėtume patikrinti hipotezę
tp_amzius = df_2023[df_2023["KATEGORIJA_KLASE"] == "Lengvieji automobiliai"]
tp_amzius.shape
Out[273]:
(1647454, 42)
In [274]:
tp_amzius = tp_amzius[tp_amzius["TP AMZIUS"] != "NaN"]
tp_amzius.shape
Out[274]:
(1540625, 42)
In [275]:
sns.set_theme(style="ticks")
plt.figure(figsize=(30, 15))
sns.pairplot(tp_amzius, hue="VALD_TIPAS", vars=["TP AMZIUS"], height=5, aspect=2)
plt.legend(title='VALD_TIPAS', loc='upper right', labels=['Fizinis', 'Juridinis'])
plt.ylabel("COUNT")
plt.show()
<Figure size 3000x1500 with 0 Axes>

Grafike matome kad Juridinių asmenų transporto priemonės koncentruojasi į mažesnį tp amžių, bet kad patvirtinti hipotezę skaičiuojame transporto priemonių amžiaus vidurkius

In [276]:
vidurkiai = tp_amzius.groupby(['VALD_TIPAS'])['TP AMZIUS'].mean().reset_index()
print(vidurkiai)
  VALD_TIPAS  TP AMZIUS
0    Fizinis   16.92889
1  Juridinis   11.10775

Pavaizduojame Vidurkius grafiškai barplot pagalba su standartiniais nuokrypiais

In [277]:
plt.figure(figsize=(10, 6))
sns.barplot(x="TP AMZIUS", y="VALD_TIPAS", data=tp_amzius, errorbar="sd")
plt.xlabel("TP AMŽIUS")
plt.ylabel("VALDYTOJAS")
plt.title("Transporto priemonių amžiaus vidurkis fiziniams ir juridiniams asmenims")
plt.show()

Antroji Hipotezė patvirtinta. Juridiniai asmenys valdo žymiai naujesnes transporto priemones, jų amžiaus vidurkis 11 metų, tuo tarpu fizinių asmenų transporto priemonių amžiaus vidurkis beveik 17 m.


Kadangi jau išsiaiškinome bendrą automobilių amžių panagrinėkime fizinius asmenis detaliau

Trečioji hipotezė "Naujausius automobilius vairuoja 30-50 m. amžiaus asmenys"

In [278]:
tp_fiz = tp_amzius[tp_amzius["VALD_TIPAS"] == "Fizinis"]
tp_fiz.shape
Out[278]:
(1335232, 42)
In [279]:
tp_amzius["AMZIAUS INT"].unique()
Out[279]:
array(['59-63', '54-58', '49-53', '64-68', '29-33', nan, '24-28', '44-48',
       '39-43', '34-38', '69-73', '79-83', '74-78', '19-23', '84-88',
       '89-93', '94-98', '99-103', '14-18', '9-13', '4-8', '-1-3',
       '104-108'], dtype=object)
In [280]:
# mažiname lenteles nes nebeužtenka RAM:)
tp_amziusfiltr = tp_amzius.drop(['VAIRAS_DESINEJE','KEB_PAVADINIMAS', 'NUOSAVA_MASE_BAZ', 'MAKS_MASE', 'DARBINIS_TURIS',  'GALIA', 'GALIA_ELEKTR', 'DEGALAI', 'ELEKTRINE_TP',   'HIBRIDINES_TP_KATEGORIJA', 'CO2_KIEKIS', 'CO2_KIEKIS_WLTP',
       'TERSALU_LYGIS', 'SPALVA', 'MAKS_GREITIS', 'SEDIMU_VIETU_SK',
       'STOVIMU_VIETU_SK', 'GAMYBOS_METAI', 'MODELIO_METAI', 'RIDA',
       'PIRM_REG_DATA', 'PIRM_REG_DATA_LT', 'PASKUTINES_REG_DATA',
       'KILMES_SALIS', 'VALD_TIPAS', 'VALD_GIM_DAT_INT'], axis=1)
In [281]:
tp_amziusfiltr.columns
Out[281]:
Index(['MARKE', 'KOMERCINIS_PAV', 'KATEGORIJA_KLASE', 'SAVIVALDYBE',
       'APSKRITIS', 'ID', 'Duomenų metai', 'VALDYTOJO METAI 1',
       'VALDYTOJO METAI2', 'AMZIUS1', 'AMZIUS2', 'AMZIAUS INT',
       'AR DIDMIESTIS', 'PAGAMINIMO METAI', 'TP AMZIUS', 'KLASE'],
      dtype='object')
In [282]:
# nufilturuojame dalį reikšmių kad matytume aiškesnį vaizdą
filtered_tp_amzius = tp_amziusfiltr[tp_amziusfiltr['TP AMZIUS'] <= 30]
In [283]:
# dar nufiltruoju nereikšmingus intervalus kad grafike galima būtų įžvelgti tendencijas
filtered_tp_amzius1 = filtered_tp_amzius[~filtered_tp_amzius['AMZIAUS INT'].isin(["-1-3", "4-8", "9-13", "14-18", "99-103", "104-108"])]
In [284]:
heatmap_data = filtered_tp_amzius1.groupby(['AMZIAUS INT', 'TP AMZIUS']).size().reset_index(name='Kiekis')
heatmap_data = heatmap_data.pivot_table(index='TP AMZIUS', columns='AMZIAUS INT', values='Kiekis', aggfunc='sum', fill_value=0)
plt.figure(figsize=(12, 8))
sns.heatmap(heatmap_data, annot=True, fmt='d', cmap='viridis', annot_kws={"size": 8})
plt.xticks(rotation=45)
plt.xlabel('AMZIAUS INT')
plt.ylabel('TP AMZIUS')
plt.title('Heatmap: TP kiekis pagal amžiaus intervalus')
plt.show()

Lentelė neinformatyvi matome kur koncentruojasi didžioji dalis automobių tačiau mes ieškome, kur yra naujausi automobiliai todėl koreguojame y ašį į vidurkius ir pasitelkiame "barplot" grafiką

In [285]:
filtered_tp_amzius2 = tp_amziusfiltr[~tp_amziusfiltr['AMZIAUS INT'].isin(["-1-3", "4-8", "9-13", "14-18", "99-103", "104-108"])]
In [286]:
plt.figure(figsize=(12, 8))
sns.barplot(x='AMZIAUS INT', y='TP AMZIUS', data=filtered_tp_amzius2, errorbar="sd")
for y_value in np.unique(filtered_tp_amzius2['TP AMZIUS']):
    plt.axhline(y=y_value, color='gray', linestyle='--', linewidth=0.8)
plt.xticks(rotation=45)
plt.xlabel('AMZIAUS INT')
plt.ylabel('TP AMZIUS')
plt.title('TP amžiaus vidurkis pagal amžiaus intervalus su standartiniu nuokrypiu')
plt.ylim(0, 40)
plt.show()
In [287]:
vidurkiai_pagal_amziu = filtered_tp_amzius2.groupby(['AMZIAUS INT'])['TP AMZIUS'].mean().reset_index()
vidurkiai_pagal_amziu
Out[287]:
AMZIAUS INT TP AMZIUS
0 19-23 18.207883
1 24-28 17.073049
2 29-33 16.243587
3 34-38 15.945052
4 39-43 15.788399
5 44-48 16.231562
6 49-53 16.804017
7 54-58 17.199149
8 59-63 17.369612
9 64-68 17.330461
10 69-73 17.943157
11 74-78 19.245406
12 79-83 20.540914
13 84-88 21.957765
14 89-93 23.628391
15 94-98 24.946176

Trečioji hipotezė patvirtinta matome, kad vidutiniškai naujausius automobilius vairuoja asmenys intervale nuo 29 iki 53 m.


Ketvirtoji Hipotezė "Didžiuosiuose Miestuose žmonės vairuoja naujesnius automobilius nei rajonuose taip pat dažniau renkasi premium markės automobilius"

In [288]:
df1 = filtered_tp_amzius2
df1.loc[df1['AR DIDMIESTIS'] == 1, 'AR DIDMIESTIS'] = 'Didmiestis'
df1.loc[df1['AR DIDMIESTIS'] == 0, 'AR DIDMIESTIS'] = 'Rajonas'
In [289]:
plt.figure(figsize=(24, 18))
sns.catplot(data=df1, x="KLASE", y="TP AMZIUS", hue="AR DIDMIESTIS", kind="box",  height=6, aspect=1.5)
plt.title('Transporto priemonių amžius ir klasė pagal gyvenama vietą')
plt.show()
<Figure size 2400x1800 with 0 Axes>

Aanalizuodami grafiką galime matyti, kad didmiesčių gyventojai vairuoja naujesnius automobilius visuose segmentuose. Patys naujausi automobiliai, kuriuos vairuoja didmiesčių gyventojai yra ekonominės klasės

In [290]:
plt.figure(figsize=(24, 18))
sns.catplot(data=df1, x="APSKRITIS", y="TP AMZIUS", hue="KLASE", kind="box",  height=6, aspect=1.5)
plt.title('Transporto priemonių amžius ir klasė pagal gyvenama vietą')
plt.ylim(0, 40)
plt.show()
<Figure size 2400x1800 with 0 Axes>

Išanalizavę automobilio amžių pagal klasę ir valdytojo gyvenamą apskritį galime daryti išvadą, kad naujausius automobilius vairuoja Vilniaus apskrities gyventojai, jų amžiaus vidurkis siekia 15 m. - Vidutinės ir Premium klasės automobiliuose ir mažiau nei 10 m. - Ekonominės klasės ir kituose automobiliuose.

Pilnai patikrinti hipotezę pasitelksime paprastą stulpelinę diagrąmą ir pažiūrėsime kuriuose miestuose valdoma daugiausiai premium klasės automobilių

In [291]:
sns.displot(df1, x="SAVIVALDYBE", hue="KLASE", multiple="dodge", height=6, aspect=4)
plt.title('Transporto priemonių amžius ir klasė pagal gyvenama vietą')
plt.xticks(rotation=90)
plt.show()

Grafike matome, kad daugiausia Premium klasės automobilių vairuoja Vilniaus, Kauno, Klaipėdos miestuose gyvenantys žmonės, tačiau pažiūrėkime kuriame mieste Premium klasės automobilių procentinė dalis didžiausia

In [292]:
premium_df = df1[df1['KLASE'] == 'Premium']
procentai_df = premium_df.groupby('SAVIVALDYBE').size() / df1.groupby('SAVIVALDYBE').size() * 100
procentai_df = procentai_df.reset_index(name='procentai')
procentai_df = procentai_df.sort_values(by='procentai',ascending=False)
plt.figure(figsize=(10, 12))
sns.barplot(data=procentai_df, x="procentai", y="SAVIVALDYBE", color='blue')
plt.xlabel("Premium automobilių procentinė dalis")
plt.show()

Apskaičiavus kokią procentinę daly kiekvienoje savivaldybėje sudaro "Premium" klasės automobilių, sitaucija visiškai pasikeitė ir Vilnius atsiduria priešpaskutinėje vietoje, o daugiausia Premium markių automobilių Neringos, Lazdijų ir Šalčininkų savivaldybėse

Ketvirtoji Hipotezė patvirtinta iš dalies, iš tiesų vidutiniškai naujausius automobilius vairuoja didmiesčių gyventojai, naujausi automobiliai yra ekonominės klasės ir važinėja Vilniuje. Premium klasės automobilių didmiesčiuose yra daugiausia, tačiau tik todėl kad čia yra daugiausia gyventojų,tikslesnius duomenis gauname jei skaičiuojame procentinę dalį Premium klasės automobilių ir čia Didieji miestai yra lentelės apatinėje dalyje.


Penktoji Hipotezė Elektra varomų automobilių lietuvoje daugėja, jai patikrinti analizuosime Lietuvos transporto priemonių lengvųjų automobilio parko pokyčius pagal transporto priemonės kuro tipą

In [293]:
# išsitrinam eilutes kur kuro tipo nėra
df2 = df[df['KATEGORIJA_KLASE'] == 'Lengvieji automobiliai']
In [294]:
df2 = df2[(df2['DEGALAI'].notna()) & (df2['DEGALAI'] != "--")]
df2['DEGALAI'].unique()
Out[294]:
array(['Benzinas', 'Dyzelinas', 'Benzinas / Elektra', 'Elektra',
       'Dyzelinas / Elektra', 'Benzinas / Etanolis', 'Benzinas / Dujos',
       'Benzinas / Suskystintos_dujos', 'Benzinas / Elektra / Dujos',
       'Benzinas / Gamtinės_dujos', 'Benzinas / Etanolis / Dujos',
       'Dujos', 'Gamtinės_dujos', 'Dyzelinas / Dujos'], dtype=object)
In [295]:
df2.shape
Out[295]:
(2410104, 42)
In [296]:
sns.displot(df2, x="DEGALAI", hue="Duomenų metai", multiple="dodge")
plt.xticks(rotation=90)
plt.show()

Pradiniai rezultatai neatrodo logiški, nes 2023 lengvųjų automobilių įrašų turime daugiau, patikrinkime pokyčius procentais:

In [297]:
df2['KIEKIS'] = df2['DEGALAI'].map(df2['DEGALAI'].value_counts())
grouped_df = df2.groupby(['DEGALAI', 'Duomenų metai']).sum().reset_index()

# Pridedame procentinį pokytį tarp metų
grouped_df['PROCENTAI'] = grouped_df.groupby('DEGALAI')['KIEKIS'].pct_change() * 100

# Pavaizduojame barplot grafiku
plt.figure(figsize=(10, 6))
sns.barplot(x='DEGALAI', y='PROCENTAI', hue='Duomenų metai', data=grouped_df)
plt.xticks(rotation=90)
plt.title('Procentinis pokytis tarp metų kiekvienai DEGALAI reikšmei')
plt.ylabel('Procentai')
plt.show()
<ipython-input-297-24b2199acf08>:2: FutureWarning: The default value of numeric_only in DataFrameGroupBy.sum is deprecated. In a future version, numeric_only will default to False. Either specify numeric_only or select only columns which should be valid for the function.
  grouped_df = df2.groupby(['DEGALAI', 'Duomenų metai']).sum().reset_index()

Suskaičiuokime kiek reikšmių kiekmietais metais nufiltravome nes jos buvo NaN arba "--"

2022:

In [298]:
df[(df['KATEGORIJA_KLASE'] == "Lengvieji automobiliai") & (df['Duomenų metai'] == 2022) & (df['DEGALAI'].isin(["--" or "NaN"]))]['KATEGORIJA_KLASE'].value_counts()
Out[298]:
Lengvieji automobiliai    292097
Name: KATEGORIJA_KLASE, dtype: int64

2023:

In [299]:
df[(df['KATEGORIJA_KLASE'] == "Lengvieji automobiliai") & (df['Duomenų metai'] == 2023) & (df['DEGALAI'].isin(["--" or "NaN"]))]['KATEGORIJA_KLASE'].value_counts()
Out[299]:
Lengvieji automobiliai    535670
Name: KATEGORIJA_KLASE, dtype: int64

Penktosios hipotezės negalime nei patvirtinti nei paneigti, kadangi 2023 m. neturime duomenų net apie 535.670 automobilių degalų tipą, kai 2022 tokių įrašų tik 292.097 esant daugiau nei 15% skirtumui teisingų išvadų padaryti negalėsime.


Na ir pabaigai pabandykime pritaikyti mašininio mokymosi algoritmą

Kadangi priklausomybės nėra aiškios ar bent nuspėjamos pabandykime jų paieškoti

In [300]:
df['PIRM_REG_DATA_LT'] = pd.to_datetime(df['PIRM_REG_DATA_LT'], infer_datetime_format=True, errors='coerce')
df["PIRM_REG_DATA_LT"].dtype
Out[300]:
dtype('<M8[ns]')
In [301]:
df['PIRM_REG_DATA'] = pd.to_datetime(df['PIRM_REG_DATA'], infer_datetime_format=True, errors='coerce')
df["PIRM_REG_DATA"].dtype
Out[301]:
dtype('<M8[ns]')
In [302]:
df["PIRM_REG_DATA_LT"].unique()
Out[302]:
array(['2022-09-28T00:00:00.000000000', '2022-03-07T00:00:00.000000000',
       '2022-03-09T00:00:00.000000000', ...,
       '1997-07-12T00:00:00.000000000', '1991-03-28T00:00:00.000000000',
       '1977-07-20T00:00:00.000000000'], dtype='datetime64[ns]')
In [303]:
df8 = df.dropna(subset=['PIRM_REG_DATA_LT'])
df8 = df.dropna(subset=['PIRM_REG_DATA'])

Markės ir pirmosios registracijos datos koreliacija

In [304]:
df8.plot.scatter(x='PIRM_REG_DATA', y='MARKE')
plt.show()

TP amžiaus ir pirmos registracijos datos koreliacija:

In [305]:
df8.plot.scatter(x='PIRM_REG_DATA_LT', y='TP AMZIUS')
plt.show()

Pirmos registracijos datos ir Klasės koreliacija

In [306]:
df8.plot.scatter(x='PIRM_REG_DATA', y='KLASE')
plt.show()

TP amžiaus ir spalvos koreliacija:

In [307]:
df8.plot.scatter(x='TP AMZIUS', y='SPALVA')
plt.show()

Spalvos ir pirmos registracijos datos koreliacija:

In [308]:
df8.plot.scatter(x='PIRM_REG_DATA', y='SPALVA')
plt.show()
In [309]:
df8 = df.dropna(subset=['GALIA'])

Galios ir pirmos registracijos datos koreliacija:

In [310]:
df8.plot.scatter(x='PIRM_REG_DATA', y='GALIA')
plt.show()

Valdytojo amžiaus ir transporto priemonės amžiaus koreliacija

In [311]:
df8.plot.scatter(x='AMZIUS1', y='TP AMZIUS')
plt.show()
In [312]:
# BUvau pasiruošęs kodą modelio apmokymui tačiau jo nepanaudojau
# from sklearn.linear_model import LinearRegression
In [313]:
# df8 = df.dropna(subset=['AMZIUS1'], inplace=True)
# df8 = df.dropna(subset=['TP AMZIUS'], inplace=True)
In [314]:
# y = df8["TP AMZIUS"]
In [315]:
# model = LinearRegression()
In [316]:
# from sklearn.model_selection import train_test_split
# train_test_split(X, y, test_size = 0.2)

Patikrinę keleta sąsajų jokių tendencijų tinkamam modelio sukūrimui nerasta...

PASIRUOŠIAME DUOMENIS POWE BI analizei, sukurdami keleta lentelių

In [319]:
savininkai= df[['ID', 'VALD_TIPAS', 'VALD_GIM_DAT_INT', "SAVIVALDYBE", 'APSKRITIS', 'AMZIUS1', 'AMZIUS2', "AMZIAUS INT", 'AR DIDMIESTIS', "Duomenų metai"]]
automobiliai = df[['ID', 'MARKE', 'KOMERCINIS_PAV', 'KATEGORIJA_KLASE', "KEB_PAVADINIMAS", 'DARBINIS_TURIS', 'GALIA', 'DEGALAI', "ELEKTRINE_TP", 'CO2_KIEKIS', 'SPALVA', "MAKS_GREITIS", "PIRM_REG_DATA", 'PIRM_REG_DATA_LT', 'KILMES_SALIS', 'TP AMZIUS', "KLASE"]]
In [321]:
# savininkai.to_csv('savininkai 2022-2023.csv', index=False)
# # automobiliai.to_csv('automobiliai 2022-2023.csv', index=False)
# from google.colab import files
# files.download('savininkai 2022-2023.csv')
# files.download('automobiliai 2022-2023.csv')